package com.gingko.duominuo.utils.compressor

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import com.gingko.duominuo.utils.compressor.Checker.isJPG
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import kotlin.jvm.Throws

/**
 * Responsible for starting compress and managing active and cached resources.
 */
internal class Engine(srcImg: String, tagImg: File) {
    private var srcExif: ExifInterface? = null
    private val srcImg: String
    private val tagImg: File
    private var srcWidth: Int
    private var srcHeight: Int

    init {
        if (isJPG(srcImg)) {
            srcExif = ExifInterface(srcImg)
        }
        this.tagImg = tagImg
        this.srcImg = srcImg
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        options.inSampleSize = 1
        BitmapFactory.decodeFile(srcImg, options)
        srcWidth = options.outWidth
        srcHeight = options.outHeight
    }

    private fun computeSize(): Int {
        srcWidth = if (srcWidth % 2 == 1) srcWidth + 1 else srcWidth
        srcHeight = if (srcHeight % 2 == 1) srcHeight + 1 else srcHeight
        val longSide = Math.max(srcWidth, srcHeight)
        val shortSide = Math.min(srcWidth, srcHeight)
        val scale = shortSide.toFloat() / longSide
        return if (scale <= 1 && scale > 0.5625) {
            if (longSide < 1664) {
                1
            } else if (longSide >= 1664 && longSide < 4990) {
                2
            } else if (longSide > 4990 && longSide < 10240) {
                4
            } else {
                longSide / 1280
            }
        } else if (scale <= 0.5625 && scale > 0.5) {
            longSide / 1280
        } else {
            Math.ceil(longSide / (1280.0 / scale)).toInt()
        }
    }

    private fun rotatingImage(bitmap: Bitmap): Bitmap {
        return srcExif?.let {
            val matrix = Matrix()
            var angle = 0
            val orientation =
                it.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
            when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90 -> angle = 90
                ExifInterface.ORIENTATION_ROTATE_180 -> angle = 180
                ExifInterface.ORIENTATION_ROTATE_270 -> angle = 270
                else -> {
                }
            }
            matrix.postRotate(angle.toFloat())
            Bitmap.createBitmap(
                bitmap,
                0,
                0,
                bitmap.width,
                bitmap.height,
                matrix,
                true
            )
        } ?: bitmap
    }

    @Throws(IOException::class)
    fun compress(): File {
        val options = BitmapFactory.Options()
        options.inSampleSize = computeSize()
        var tagBitmap = BitmapFactory.decodeFile(srcImg, options)
        val stream = ByteArrayOutputStream()
        tagBitmap = rotatingImage(tagBitmap)
        tagBitmap.compress(Bitmap.CompressFormat.JPEG, 60, stream)
        tagBitmap.recycle()
        FileOutputStream(tagImg).use { fos ->
            fos.write(stream.toByteArray())
            fos.flush()
        }
        stream.close()
        return tagImg
    }


}